local oo = require("SharedLibs.BaseLib")
local co = require("SharedLibs.CoroLib")

Debugger = require("SharedLibs.Debugger")

IReadOnlyProperty = require("SharedLibs.Signal.IReadOnlyProperty")
ISignal = require("SharedLibs.Signal.ISignal")
Signal = require("SharedLibs.Signal.Signal")

--[[
	将一个属性的数据隐射为另外一种数据类型(或值)

	注意: Map后的Property每次GetValue时都要执行一次Map函数. 如果Map的嵌套层次很高, 有可能有性能问题
	如果出现性能问题, 上层可以自行实现cache, 也就是如果parent的值没有变化, 并且parent不是table或Instance.
	就可以不用Map, 直接返回cache的值
]] 
local cls = oo.class();
cls:implements(IReadOnlyProperty);

--- mapper接收任意个参数(...)， 返回任意个值 (...)
--- 注意：和SignalWrapper不同，PropertyWrapper不会过滤数据，只会对数据进行映射
function cls:constructor(property, mapper, name)
	assert(property);
	assert(mapper);

	self.name = name or oo.GetClassName(cls);

	self._changed = Signal.new("PropertyChanged");
	self._listenerCount = 0;

	self._p = property;
	self._mapper = mapper;

	--- parent value
	local pVal = self._p:GetValue();
	self._val = self._mapper(pVal);
end

function cls:GetValue()
	local val = self._mapper(self._p:GetValue());
	self._val = val;
	return val;
end

function cls:On(handler, retDestroyer)	
	self._listenerCount = self._listenerCount + 1;
	self._changed:On(handler);

	if self._listenerCount == 1 then
		self._onPChanged = function(value)
			local newVal = self._mapper(value);
			if newVal ~= self._val then
				self._val = newVal;
				self._changed:Emit(newVal);
			end
		end
		self._p:On(self._onPChanged);
	end

	if retDestroyer then return function() self:Off(handler); end end		
end

function cls:Off(listener)
	if self._listenerCount == 0 then return end;
	
	self._listenerCount = self._listenerCount - 1;
	assert(self._listenerCount >= 0);
	self._changed:Off(listener);

	if self._listenerCount == 0 then
		self._p:Off(self._onPChanged);
		self._onPChanged = nil;
	end
end

function cls:Clear()
	local needOff = self._listenerCount ~= 0;
	self._listenerCount = 0;
	self._changed:Clear();

	if needOff then
		self._p:Off(self._onPChanged);
		self._onPChanged = nil;
	end
end

return cls;
